package com.acxy.ants.core;

import com.acxy.ants.common.kit.JsonMap;
import com.acxy.ants.common.kit.StrKit;
import com.acxy.ants.core.config.AntsConfig;
import com.acxy.ants.core.config.Constants;
import com.acxy.ants.core.config.Handlers;
import com.acxy.ants.core.kit.ScanKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 框架进入点根据过滤器
 * 初始化插件
 * 初始化常量
 * 初始化路由
 * 初始化视图
 *
 * @author MrShun
 * @version 1.0
 * @Date 2017-04-26
 */
@WebFilter(filterName = "AntsFilter", urlPatterns = "/*")
public class AntsFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(AntsFilter.class);

    //常量
    private Constants constants;

    //Handler链表
    private Handlers handler;

    //项目字符串长度
    private int contextPathLength;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        JsonMap map = ScanKit.getApplicationConfig();
        //默认从web.xml配置文件里面加载
        String configClass = filterConfig.getInitParameter("configClass");
        String modulesStr = filterConfig.getInitParameter("modules");
        String[] modules;
        if (StrKit.notBlank(configClass) && map == null) {
            throw new RuntimeException("在web.xml中缺少了AntsFilter配置 或缺少@Application注解");
        }else {
            if(StrKit.isBlank(configClass)) {
                configClass = map.getStr("configClass");
                modules = (String[]) map.get("modules");
            }else{
                modules = StrKit.isBlank(modulesStr)? null: modulesStr.split(",");
            }
        }
        try {
            AntsConfig antsConfig = createAntsConfig(configClass);
            AntsContext ants = new AntsContext(antsConfig, modules, filterConfig.getServletContext());
            handler = ants.getHandlers();
            constants = ants.getConstants();

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Ants init error!");
        }

        String contextPath = filterConfig.getServletContext().getContextPath();
        contextPathLength = (contextPath == null || "/".equals(contextPath)) ? 0 : contextPath.length();
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // 获取 request、response，设置编码
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        request.setCharacterEncoding(constants.getEncoding());
        response.setCharacterEncoding(constants.getEncoding());
        String target = request.getRequestURI();
        if (contextPathLength > 0)
            target = target.substring(contextPathLength);
        String[] resources = constants.getResources();
        //定义一个标志位
        boolean[] isHandled = {false};
        if (resources != null && resources.length != 0) { //判断是否有静态资源
            for (String resource : resources) {
                if (target.startsWith(resource)) { //存在静态资源就拦截 修改标志位
                    isHandled[0] = true;
                    break;
                }
            }
        }

        if (isHandled[0])
            chain.doFilter(request, response);
        else {
            try {
                //交给handler处理
                boolean execute = handler.execute(target, request, response);
                //当标志为true不执行下个过滤器
                if (execute) {
                    chain.doFilter(request, response);
                }
            } catch (Exception e) {
                if (logger.isErrorEnabled()) {
                    String qs = request.getQueryString();
                    logger.error(qs == null ? target : target + "?" + qs, e);
                }
            }
        }
    }

    @Override
    public void destroy() {
        System.exit(0);
    }


    private AntsConfig createAntsConfig(String configClass) {
        if (configClass == null) {
            throw new RuntimeException("Please set configClass parameter of AntsFilter in web.xml or @Application");
        }

        Object temp = null;
        try {
            temp = Class.forName(configClass).newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Can not create instance of class: " + configClass, e);
        }

        if (temp instanceof AntsConfig) {
            return (AntsConfig) temp;
        } else {
            throw new RuntimeException("Can not create instance of class: " + configClass + ". Please check the config in web.xml or @Application");
        }
    }
}
